/**
 * <copyright>
 * Hui SONG, Peking University
 * </copyright>
 *
 * $Id: WrappingEObjectImpl.java,v 1.5 2008/11/22 02:57:04 song Exp $
 */
package cn.edu.pku.sei.ra.wrapping.CommonWrapping.impl;

import cn.edu.pku.sei.ra.wrapping.CommonWrapping.CommonWrappingPackage;
import cn.edu.pku.sei.ra.wrapping.CommonWrapping.WaitingPair;
import cn.edu.pku.sei.ra.wrapping.CommonWrapping.WrappingEObject;
import cn.edu.pku.sei.ra.wrapping.CommonWrapping.util.CommonWrappingAdapterFactory;
import cn.edu.pku.sei.ra.wrapping.CommonWrapping.util.WrappingEObjectAdapterImpl;

import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import java.util.Collection;
import java.util.Iterator;

import org.eclipse.emf.common.notify.NotificationChain;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.impl.EObjectImpl;

import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Wrapping EObject</b></em>'.
 * <p/>
 * This is the super class of every *Impl Class generated by SandTablist Framework, 
 * Some of its methods are the so called "hook" methods. Subsequent developers need 
 * to overwrite some of these hook classes with the code specific to the objective
 * management capability. From this perspective, these hook classes is the bridge 
 * between the common MOF reflection like interface and the platform specific operation
 * method.
 * <p/>
 * Every instance of WrappingEObject (or sub Classes) contain a "core" indicating a 
 * unique manageable element in the running system. Most of the operations, like life-
 * cycle control, getting/setting attributes or references are executed using this core.
 * 
 * 
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link cn.edu.pku.sei.ra.wrapping.CommonWrapping.impl.WrappingEObjectImpl#getWaitingFeature <em>Waiting Feature</em>}</li>
 *   <li>{@link cn.edu.pku.sei.ra.wrapping.CommonWrapping.impl.WrappingEObjectImpl#getCore <em>Core</em>}</li>
 *   <li>{@link cn.edu.pku.sei.ra.wrapping.CommonWrapping.impl.WrappingEObjectImpl#isNewborn <em>Newborn</em>}</li>
 *   <li>{@link cn.edu.pku.sei.ra.wrapping.CommonWrapping.impl.WrappingEObjectImpl#isDead <em>Dead</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class WrappingEObjectImpl extends EObjectImpl implements WrappingEObject {
	/**
	 * The default value of the '{@link #getWaitingFeature() <em>Waiting Feature</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getWaitingFeature()
	 * @generated
	 * @ordered
	 */
	protected static final int WAITING_FEATURE_EDEFAULT = -1;
	/**
	 * The cached value of the '{@link #getWaitingFeature() <em>Waiting Feature</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getWaitingFeature()
	 * @generated
	 * @ordered
	 */
	protected int waitingFeature = WAITING_FEATURE_EDEFAULT;
	/**
	 * The default value of the '{@link #getCore() <em>Core</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getCore()
	 * @generated
	 * @ordered
	 */
	protected static final Object CORE_EDEFAULT = null;
	/**
	 * The default value of the '{@link #isNewborn() <em>Newborn</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isNewborn()
	 * @generated
	 * @ordered
	 */
	protected static final boolean NEWBORN_EDEFAULT = false;
	/**
	 * The cached value of the '{@link #isNewborn() <em>Newborn</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isNewborn()
	 * @generated
	 * @ordered
	 */
	protected boolean newborn = NEWBORN_EDEFAULT;
	/**
	 * The default value of the '{@link #isDead() <em>Dead</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isDead()
	 * @generated
	 * @ordered
	 */
	protected static final boolean DEAD_EDEFAULT = false;
	/**
	 * The cached value of the '{@link #isDead() <em>Dead</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isDead()
	 * @generated
	 * @ordered
	 */
	protected boolean dead = DEAD_EDEFAULT;
	protected Object core=null;
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	protected WrappingEObjectImpl() {
		super();
		this.eAdapters().add(new WrappingEObjectAdapterImpl());
		newborn=false;
		dead=false;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	@Override
	protected EClass eStaticClass() {
		return CommonWrappingPackage.Literals.WRAPPING_EOBJECT;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public int getWaitingFeature() {
		return waitingFeature;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void setWaitingFeature(int newWaitingFeature) {
		int oldWaitingFeature = waitingFeature;
		waitingFeature = newWaitingFeature;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CommonWrappingPackage.WRAPPING_EOBJECT__WAITING_FEATURE, oldWaitingFeature, waitingFeature));
	}

	/**
	 * <!-- begin-user-doc -->
	 * Used to obtain the Core Object wrapped inside the WrappingEObject, 
	 * if the core is null currently, this method will try to lookup or 
	 * create one.
	 * <p/>
	 * It is NOT recommended to overwrite this method in the sub classes
	 * 
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public Object getCore() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		if(core!=null)
			return core;
		if(dead)
			return null;
		core=lookupCore();
		if(core==null)
			core=createCore();
		if(core==null)
			return null;
//		if(waitingFeature!=this.NO_WAITING){
//			WrappingEObject container=(WrappingEObject)eContainer();
//			container.addSubCore(this, waitingFeature);
//			waitingFeature=NO_WAITING;
//		}
			
		return core;
	}

	/**
	 * <!-- begin-user-doc -->
	 * Just set the Core Object.
	 * 
	 * Not recommended to overwrite
	 * <!-- end-user-doc -->
	 * @generated NOT;
	 */
	public void setCore(Object newCore) {
		// TODO: implement this method to set the 'Core' attribute
		// Ensure that you remove @generated or mark it @generated NOT
		this.core=newCore;
	}

	/**
	 * <!-- begin-user-doc -->
	 * check if the WrappingEObect is just born, and decide if to remove it.
	 * 
	 * NOT recommended to overwrite
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public boolean isNewborn() {
		return newborn;
	}

	/**
	 * <!-- begin-user-doc -->
	 * 
	 * mark a WrappingEObject as new born or not
	 * 
	 * NOT recommended to overwrite
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void setNewborn(boolean newNewborn) {
		boolean oldNewborn = newborn;
		newborn = newNewborn;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CommonWrappingPackage.WRAPPING_EOBJECT__NEWBORN, oldNewborn, newborn));
	}

	/**
	 * <!-- begin-user-doc -->
	 * check if a WrappingEObject is useless
	 * 
	 * NOT recommended to overwrite
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public boolean isDead() {
		return dead;
	}

	/**
	 * <!-- begin-user-doc -->
	 * 
	 * mark a WrappingEObject as dead or not
	 * 
	 * NOT recommended to overwrite 
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void setDead(boolean newDead) {
		boolean oldDead = dead;
		dead = newDead;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CommonWrappingPackage.WRAPPING_EOBJECT__DEAD, oldDead, dead));
	}

	/**
	 * <!-- begin-user-doc -->
	 * 
	 * HOOK!
	 * <p>
	 * look up a manageable element according to attributes values in this WrappingEObject.
	 * rewriting it can avoid instantiating duplicated manageable elements
	 * 
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public Object lookupCore() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		return null;
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p>
	 * instantiate a new manageable element in the objective system, according the attribute values
	 * of this WrappingEObject.
	 * <p>
	 * need to rewrite, ONLY IF you wish to use the model to create new management elements. If not 
	 * rewritten, when the use want to a new element, he will receive an "UnsuportedOperationException"
	 * for warning
	 * 
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public Object createCore() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		return null;
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * 
	 * add a sub core into the proper location after the wrappingEObject has
	 * been added into a multi-valued reference
	 * <p/>
	 * {@code 
	 *     
	 *      switch(featureID){
	 *		case XxxPackage.XXX__XXX1:
	 *			//get the list of cores for XXX__XXX1 reference
	 *			break;
	 *		case XxxPackage.XXX__XXX2:
	 *			//get the list of cores for XXX__XXX2 reference
	 *			break;
	 *		...
	 *		}
	 *	}
	 * 
	 * <p/>
	 * it is possible that you call addSubCore, but the sub WrappingEObject do
	 * not have a core yet, and you may wish to re-add it later automatically.
	 * if you need this help, remember to add
	 * {@code
	 * if(!super.addSubCore(wrappingEObject,featureID))
	 * 		return false;
	 * }
	 * 
	 * in the front of the rewritten implementation.
	 * <p/>
	 * need to rewrite ONLY IF this WrappingEObject has multi-valued references,
	 * and this references need to be changed though the model side.
	 * <!-- end-user-doc -->
	 * 
	 * @param wrappingEObject: the sub wrappingEObject to add
	 * @param featureID: the reference's feature id
	 * 
	 * @return if the add operation has been executed successfully
	 * @generated NOT
	 */
	public boolean addSubCore(WrappingEObject wrappingEObject, int featureID) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		if(wrappingEObject.getCore()==null){
			wrappingEObject.setWaitingFeature(featureID);
			return false;
		}
		return true;
	}
	
	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * remove a sub core from a reference
	 * <p/>
	 * if you wish to destroy the manageable element automatically after remove 
	 * it from the reference, invoke 
	 * {@code
	 * super.removeSubCore(wrappingEObject,featureID);
	 * }
	 * </code>
	 * to destroy the core;
	 * <p/>
	 * need to rewrite ONLY IF this WrappingEObject has multi-valued references,
	 * and this references need to be changed though the model side.
	 * <!-- end-user-doc -->
	 * 
	 * @param wrappingEObject: the sub wrappingEObject to add
	 * @param featureID: the reference's feature id
	 * @generated NOT
	 */
	public void removeSubCore(WrappingEObject wrappingEObject, int featureID) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		wrappingEObject.destroyCore();
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * return a list of sub cores for a specific reference. the result is the base for
	 * reconstruct this reference with WrappingEObjects reflecting the current system 
	 * state.
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public List listSubCores(int featureID) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		return null;
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * check if an manageable element is just the the one this WrappingEObject wraps.
	 * the result is the main base to decide if an manageable element has been 
	 * reflected in the model
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public boolean isForCore(Object core) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		return false;
	}


	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * destroy the corresponding manageable element in the objective system
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void destroyCore() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * add value to a multi-valued attribute
	 * 
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public boolean addAttribute(Object value, int index, int featureID) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * HOOK!
	 * <p/>
	 * remove value from a multi-valued attribute
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public boolean removeAttribute(Object value, int index, int featureID) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * get the proper EClass for the WrappingEObject to wrap a manageable element indicated 
	 * by parameter "object".
	 * <p/>
	 * usually in a format like
	 * {@code  
	 *      switch(featureID){
	 *		case XxxPackage.XXX__XXX1:
	 *			if(SomeCondition(object))
	 *				return XXXPackage.eINSTANCE.getSomeEClass();
	 *			break;
	 *		...
	 *		}
	 * }
	 * <p/>
	 * need to rewrite ONLY IF the type of some reference is an abstract EClass.
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EClass getChildClassMap(Object object) {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case CommonWrappingPackage.WRAPPING_EOBJECT__WAITING_FEATURE:
				return new Integer(getWaitingFeature());
			case CommonWrappingPackage.WRAPPING_EOBJECT__CORE:
				return getCore();
			case CommonWrappingPackage.WRAPPING_EOBJECT__NEWBORN:
				return isNewborn() ? Boolean.TRUE : Boolean.FALSE;
			case CommonWrappingPackage.WRAPPING_EOBJECT__DEAD:
				return isDead() ? Boolean.TRUE : Boolean.FALSE;
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case CommonWrappingPackage.WRAPPING_EOBJECT__WAITING_FEATURE:
				setWaitingFeature(((Integer)newValue).intValue());
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__CORE:
				setCore(newValue);
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__NEWBORN:
				setNewborn(((Boolean)newValue).booleanValue());
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__DEAD:
				setDead(((Boolean)newValue).booleanValue());
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case CommonWrappingPackage.WRAPPING_EOBJECT__WAITING_FEATURE:
				setWaitingFeature(WAITING_FEATURE_EDEFAULT);
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__CORE:
				setCore(CORE_EDEFAULT);
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__NEWBORN:
				setNewborn(NEWBORN_EDEFAULT);
				return;
			case CommonWrappingPackage.WRAPPING_EOBJECT__DEAD:
				setDead(DEAD_EDEFAULT);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case CommonWrappingPackage.WRAPPING_EOBJECT__WAITING_FEATURE:
				return waitingFeature != WAITING_FEATURE_EDEFAULT;
			case CommonWrappingPackage.WRAPPING_EOBJECT__CORE:
				return CORE_EDEFAULT == null ? getCore() != null : !CORE_EDEFAULT.equals(getCore());
			case CommonWrappingPackage.WRAPPING_EOBJECT__NEWBORN:
				return newborn != NEWBORN_EDEFAULT;
			case CommonWrappingPackage.WRAPPING_EOBJECT__DEAD:
				return dead != DEAD_EDEFAULT;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (waitingFeature: ");
		result.append(waitingFeature);
		result.append(", newborn: ");
		result.append(newborn);
		result.append(", dead: ");
		result.append(dead);
		result.append(')');
		return result.toString();
	}

} //WrappingEObjectImpl
